package features.advance.demo;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.UUID;

/**
 * @author LIN
 * @date 2022-05-15 13:23
 */
public class AESUtils {

    private final static String AES ="AES";
    private final static String UTF8 ="UTF-8";
//    定义⼀个的初始向量16byte
    private static final String IV_STRING ="Linsk110011ksniL";
    /**
     * 产⽣⼀个16位的密钥字符串
     *
     * @return
     */
    public static String generateSecreKey(){
        String uuid = UUID.randomUUID().toString();
        uuid = uuid.replaceAll("-","");
        return uuid.substring(0,16);
    }
    public static String aesEncry(String content,String key) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
        byte[] contentByte = content.getBytes(UTF8);
        byte[] keyByte = key.getBytes();
//        初始化⼀个密钥对象
        SecretKeySpec keySpec =new SecretKeySpec(keyByte ,AES);
//        初始化⼀个初始向量
//        不传⼊的话，则默认⽤全0的初始向量

        byte[] initParam = IV_STRING.getBytes();
        IvParameterSpec ivSpec =new IvParameterSpec(initParam);
//        指定加密的算法、⼯作模式和填充⽅式

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec,ivSpec);
        byte[] encryptedBytes = cipher.doFinal(contentByte);
        String encodedString = Base64.getEncoder().encodeToString(encryptedBytes);
        return encodedString;
    }

    public static void main(String[] args) throws Exception {
        String key = "cc3cd2568a8c899e";
        String content = "123";
        String s = aesEncry(content, key);
        System.out.println(s);
        String s1 = aesDecry(s, key);
        System.out.println(s1);
    }

    public static String aesDecry(String content, String key) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
        byte[] contentByte = Base64.getDecoder().decode(content);
        byte[] result = aesDecry(contentByte, key);
        return new String(result,"UTF-8");
    }

    public static byte[] aesDecry(byte[] contentByte, String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
//        contentByte = Base64.getDecoder().decode(contentByte);
        byte[] keyByte = key.getBytes();
//        初始化⼀个密钥对象

        SecretKeySpec keySpec =new SecretKeySpec(keyByte ,AES);
//        初始化⼀个初始向量
//        不传⼊的话，则默认⽤全0的初始向量
        byte[] initParam = IV_STRING.getBytes();
        IvParameterSpec ivSpec =new IvParameterSpec(initParam);
// 指定加密的算法、⼯作模式和填充⽅式
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec,ivSpec);
        return cipher.doFinal(contentByte);
    }
}
